<template>
  <Dialog
    v-model:visible="dialog.visible"
    modal
    :header="dialogTitle"
    @show="openHandler"
    @hide="closeHandler"
  >
    <el-form
      ref="dataForm"
      :rules="formRules"
      :model="entity"
      :disabled="operation == 3"
    >
      <el-row :gutter="20">
        <el-col :span="24">
          <el-form-item prop="roleName" label="角色名称">
            <InputText
              v-model="entity.roleName"
              placeholder="请输入角色名称"
              :disabled="entity.roleBuiltIn"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="24">
          <el-form-item prop="roleEnable" label="角色是否启用">
            <ToggleSwitch
              v-model="entity.roleEnable"
              :disabled="entity.roleBuiltIn"
            />
          </el-form-item>
        </el-col>
      </el-row>

      <Tabs v-model:value="clientId">
        <TabList>
          <Tab
            v-for="client in clients"
            :key="client.id"
            :value="client.clientId"
            >{{ client.clientName }}</Tab
          >
        </TabList>
        <TabPanels>
          <TabPanel
            v-for="client in clients"
            :key="client.id"
            :value="client.clientId"
          >
            <el-form-item prop="menuIds" label="权限">
              <TreeTable :value="client.menus">
                <Column field="menuName" header="名称" expander>
                  <template #body="scope">
                    {{ scope.node.data.menuName }}
                    <Badge
                      v-if="scope.node.data.menuType == 'AUTHORITY'"
                      value="权限"
                    />
                  </template>
                </Column>
                <Column field="menuPermission" header="权限" />

                <Column header="授权">
                  <template #body="scope">
                    <ToggleSwitch
                      v-if="scope.node.data.menuName"
                      v-model="scope.node.data.checked"
                      :disabled="scope.node.data.disabled"
                      @change="permissionChangeHandler(scope.node.data)"
                    />
                  </template>
                </Column>
                <Column header="设为首页">
                  <template #body="scope">
                    <ToggleSwitch
                      v-if="scope.node.data.menuType == 'MENU'"
                      v-model="scope.node.data.index"
                      :disabled="!scope.node.data.checked"
                      @change="indexChangeHandler(scope.node.data)"
                    />
                  </template>
                </Column>
              </TreeTable>
            </el-form-item>
          </TabPanel>
        </TabPanels>
      </Tabs>
    </el-form>

    <template #footer>
      <cancel-button @click="dialog.visible = false" />
      <save-button
        v-if="operation != 3"
        :loading="loading"
        @click="saveHandler"
      />
    </template>
  </Dialog>
</template>
<script>
import { tree2TableData } from '@/utils'

import { getDetail, save, update } from '@/api/upms/role'
import { fetchTree } from '@/api/upms/menu'
import { fetchList as fetchClientList } from '@/api/upms/oauth2Client'

import Badge from 'primevue/badge'
import OverlayBadge from 'primevue/overlaybadge'

export default {
  name: 'RoleEdit',
  props: {
    dialog: {
      type: Object,
      required: true,
    },
  },
  emits: ['success'],
  data() {
    return {
      loading: false,
      entity: {},
      formRules: {
        roleName: [
          { required: true, message: '请输入角色名称', trigger: 'blur' },
        ],
      },
      titleMap: {
        1: '新建角色表',
        2: '编辑角色表',
        3: '查看角色表',
      },
      clients: [],
      clientId: '',
    }
  },
  computed: {
    operation() {
      return this.dialog.operation
    },
    dialogTitle() {
      return this.titleMap[this.dialog.operation]
    },
  },
  components: {
    Badge,
    OverlayBadge,
  },
  methods: {
    async openHandler() {
      let res = await fetchClientList({ menuRelated: true })
      this.clients = res.data.data.records
      this.clientId = this.clients[0].clientId

      if (this.operation == 1) {
        this.entity = { roleEnable: true }
      } else {
        let res = await getDetail(this.dialog.entity.id)
        this.entity = res.data.data
      }

      for (let i in this.clients) {
        this.fetchMenuTree(this.clients[i])
      }
    },
    closeHandler() {
      this.entity = {}
    },
    fetchMenuTree(client) {
      let findGranted = (menuId) => {
        for (let i in this.entity.roleMenus) {
          let roleMenu = this.entity.roleMenus[i]
          if (roleMenu.menuId == menuId) {
            return roleMenu
          }
        }
        return null
      }

      fetchTree(client.clientId).then((res) => {
        let menus = res.data.data
        for (let j in menus) {
          let menu = menus[j]
          let roleMenu = findGranted(menu.id)
          if (roleMenu) {
            menu.checked = true
            menu.disabled = roleMenu.builtIn
            menu.index = roleMenu.index
          } else {
            menu.checked = false
            menu.index = false
          }

          for (let k in menu.children) {
            let child = menu.children[k]
            roleMenu = findGranted(child.id)
            if (roleMenu) {
              child.checked = true
              child.disabled = roleMenu.builtIn
              child.index = roleMenu.index
            } else {
              child.checked = false
              child.index = false
            }

            for (let l in child.children) {
              let permission = child.children[l]
              roleMenu = findGranted(permission.id)
              if (roleMenu) {
                permission.checked = true
                permission.disabled = roleMenu.builtIn
                permission.index = roleMenu.index
              } else {
                permission.checked = false
                permission.index = false
              }
            }
          }
        }
        client.menus = tree2TableData(menus, 'id', 'menuName')
      })
    },

    saveHandler() {
      this.$refs.dataForm.validate((valid) => {
        if (valid) {
          this.loading = true

          let data = {
            id: this.entity.id,
            roleName: this.entity.roleName,
            roleEnable: this.entity.roleEnable,
            menuIds: [],
            indexMenuIds: [],
          }

          for (let i in this.clients) {
            let client = this.clients[i]
            for (let j in client.menus) {
              let menu = client.menus[j]
              if (menu.checked) {
                data.menuIds.push(menu.id)
                if (menu.index) {
                  data.indexMenuIds.push(menu.id)
                }
              }

              for (let k in menu.children) {
                let child = menu.children[k]
                if (child.checked) {
                  data.menuIds.push(child.id)
                  if (child.index) {
                    data.indexMenuIds.push(child.id)
                  }
                }

                for (let l in child.children) {
                  let permission = child.children[l]
                  if (permission.checked) {
                    data.menuIds.push(permission.id)
                  }
                }
              }
            }
          }

          let edit = this.operation == 1 ? save : update
          edit(data)
            .then(() => {
              this.dialog.visible = false
              this.$message.success('保存成功')
              this.$emit('success')
            })
            .finally(() => {
              this.loading = false
            })
        }
      })
    },
    permissionChangeHandler(row) {
      if (!row.checked) {
        row.index = false
      }

      for (let i in row.children) {
        let child = row.children[i]
        child.checked = row.checked

        for (let j in child.children) {
          child.children[j].checked = row.checked
        }
      }
    },
    indexChangeHandler(row) {
      if (!row.index) {
        return
      }

      let menus
      for (let i in this.clients) {
        let client = this.clients[i]
        if (client.clientId == this.clientId) {
          menus = client.menus
          break
        }
      }

      for (let i in menus) {
        let menu = menus[i]
        if (menu.id == row.id) continue

        if (menu.menuType == 'MENU') {
          menu.index = false
        } else if (menu.menuType == 'CATALOG') {
          for (let k in menu.children) {
            let child = menu.children[k]
            if (child.id == row.id) continue

            if (child.menuType == 'MENU') {
              child.index = false
            }
          }
        }
      }
    },
  },
}
</script>
